package com.fingard.dsp.bank.directbank.lsbank01;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;

import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.net.ConnState;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.xml.XmlReadMode;
import com.fingard.xml.XmlTextReader;

/**
 * Created by aaron on 2018/4/4.
 */
public class LSBANK01Base extends DirectBase implements ITcpClient {
    /**
     * 获取字符编码
     *
     * @return 配置文件字符编码
     */
    protected String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    protected String[] sendToBank(Map<String, String> params, ReqRespHeader reqRespHeader, String opname) throws Exception {
        String reqParam = "";
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            sb.append(String.format("<%1$s>%2$s</%1$s>", entry.getKey(), entry.getValue()));
        }
        reqParam = sb.toString();
        String opReq = "";
        String reqDate = "";
        String serialNo = generateSerialNo(reqRespHeader);
        reqDate = serialNo.substring(0, "yyyyMMddHHmmss".length());
        opReq = String.format("<opReq><opname>%1$s</opname>" +
                        "<cstNo>%2$s</cstNo>" +
                        "<userNo>%3$s</userNo>" +
                        "<serialNo>%4$s</serialNo>" +
                        "<userId>%5$s</userId>" +
                        "<reqTime>%6$s</reqTime>" +
                        "<ReqParam>%7$s</ReqParam></opReq>", opname, bankFront.org, bankFront.operator, serialNo, bankFront.loginName,
                reqDate, reqParam);
        String[] signDatas = new String[]{"", ""};
        String signXml = String.format("<?xml version=\"1.0\" encoding=\"gb2312\"?>" +
                "<msg>" +
                "<msg_head>" +
                "<msg_type>0</msg_type>" +
                "<msg_id>1005</msg_id>" +
                "<msg_sn>0</msg_sn>" +
                "<version>1</version>" +
                "</msg_head>" +
                "<msg_body>" +
                "<origin_data_len>%d</origin_data_len>" +
                "<origin_data>%s</origin_data>" +
                "</msg_body>" +
                "</msg>", opReq.getBytes("GB2312").length, opReq);
        WriteBankLogLn2("发送签名的报文 - " + signXml);
        TcpPortClient tmpClient = new TcpPortClient(bankFront.signURL, Integer.parseInt(bankFront.signPort), this);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(signXml.getBytes("GB2312"));
        signDatas[0] = tmpReceiver.connState;
        if (signDatas[0].length() > 0) {
            signDatas[1] = tmpReceiver.getConnMsg();
            return signDatas;
        }
        if (tmpReceiver.recBytes != null) {
            signDatas[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.recBytes.length, "GB2312");
        }
        StringBuilder tmpSbXml = new StringBuilder();
        XmlTextReader tmpBkReader = loadBankRespXmlReader(signDatas[1], tmpSbXml);
        WriteBankLogLn("收到签名数据 - " + signDatas[1]);

        //签名后的数据
        String[] result = {"", ""};
        if(tmpBkReader==null){
            result[0] = ConnState.FAIL;
            result[1] = "签名报文格式有误，交易序列号:"+serialNo;
            return result;
        }
        if (signDatas[1].indexOf("<signed_data>") == -1) {
            result[0] = ConnState.FAIL;
            result[1] = "签名失败，错误代码为" + tmpBkReader.getFirstText("/msg/msg_body/error_no");
            return result;
        }

        String SignedData = tmpBkReader.getFirstText("/msg/msg_body/signed_data").replace("\r", "").replace("\n", "");
        String xml = String.format("<?xml version=\"1.0\" encoding=\"GBK\"?>" +
                "<BankData><Sign><SignedData>%s</SignedData>" +
                "<PubKey></PubKey></Sign>%s</BankData>", SignedData, opReq);
        String header = String.format("%s%s%08d", serialNo,
                StringUtils.repeat("0", 25 - opname.length())+ opname, xml.length());
        xml = header + xml;

        WriteBankLogStep2(xml);
        WebRequest webRequest = new WebRequest(bankFront.serverURL);
        result = webRequest.upload(xml.getBytes(getCharset()), getCharset());
        WriteBankLogStep3(result[1]);

        //移除报文头
        if(result[0].length()==0) {
            result[1] = result[1].substring(56);
        }
        return result;
    }

    protected String generateSerialNo(ReqRespHeader reqRespHeader) {
        if (StringUtils.isEmpty(reqRespHeader.payDateTime)) {
            reqRespHeader.payDateTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        }
        String headerPart = String.format("%s%s%s%s", getCommonReqDate(reqRespHeader), "803", bankFront.loginName, getLength4SeqId(reqRespHeader));
        return headerPart;
    }

    String busDateTime14;

    String  seqId;

    protected String getCommonReqDate(ReqRespHeader reqRespHeader) {
        if (busDateTime14 == null) {
            Date busDate = reqRespHeader.getBusTime(new Date());
            busDateTime14 = DateFormatUtils.format(busDate, "yyyyMMddHHmmss");
        }
        return busDateTime14;
    }

    protected String getLength4SeqId(ReqRespHeader reqRespHeader) {
        String seqId = reqRespHeader.reqSeqID;
        if (seqId == null) {
            seqId = reqRespHeader.transSeqID;
        }
        if (seqId.length() < 4) {
            return StringUtils.repeat("0", 4 - seqId.length()) + seqId;
        }
        return seqId.substring(seqId.length() - 4);
    }


    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {

    }

    protected String getHostReturnCode(XmlTextReader xmlTextReader) throws Exception {
        xmlTextReader.resetReadMode(XmlReadMode.JustInnerText);
        return xmlTextReader.getFirstText("/BankData/opRep/hostReturnCode");
    }

    protected String getHostErrorMessage(XmlTextReader xmlTextReader) throws Exception {
        xmlTextReader.resetReadMode(XmlReadMode.JustInnerText);
        return xmlTextReader.getFirstText("/BankData/opRep/hostErrorMessage");
    }

    protected boolean isSuccess(String returnCode) {
        try {
            if (Integer.valueOf(returnCode) == 0) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 去除金额前面多余的0
     * @param amount
     * @return
     */
    protected String removePrefix(String amount){
        if(amount==null){
            return "0.00";
        }
        amount = amount.replaceFirst("^0*","");
        if(amount.startsWith(".")){
            return 0+amount;
        }
        return amount;
    }
}
